package com.esun.payment_api.service.impl;

import com.esun.common.api.CommonResult;
import com.esun.common.bean.PageRequest;
import com.esun.common.utils.*;
import com.esun.payment_api.bean.UserBean;
import com.esun.payment_api.domain.*;
import com.esun.payment_api.mapper.CompanyMapper;
import com.esun.payment_api.mapper.DepartmentMapper;
import com.esun.payment_api.mapper.UserMapper;
import com.esun.payment_api.security.model.LoginBody;
import com.esun.payment_api.security.model.LoginByOpenIdBody;
import com.esun.payment_api.service.LoginService;
import com.esun.payment_api.security.AjaxResult;
import com.esun.payment_api.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class LoginServiceImpl implements LoginService {

    @Resource
    UserMapper userMapper;

    @Resource
    CompanyMapper companyMapper;

    @Resource
    DepartmentMapper departmentMapper;

    @Override
    public CommonResult<UserBean> loginByPassword(LoginBody loginBody){
        //以后这里的参数要从系统表中获取。
        final Integer ALLOWED_ERROR_TIME = 5;
        final Integer LOCK_MINUTES = 3;

        System.out.println("loginByPassword");
        if(loginBody.getUsername()==null){
            //return CommonResult.failed("用户名为空");
            return CommonResult.failed("用户名或密码错误");
        }
        if(loginBody.getPassword()==null){
            //return CommonResult.failed("密码为空");
            return CommonResult.failed("用户名或密码错误");
        }

        HashMap<String, String> map = new HashMap<>();
        map.put("loginName", loginBody.getUsername());
        if (loginBody.getCompanyId()!=null){
            map.put("companyId", loginBody.getCompanyId().toString());
        }
        if (loginBody.getDepartmentId()!=null){
            map.put("departmentId", loginBody.getDepartmentId().toString());
        }
        PageRequest pageRequest = new PageRequest();
        pageRequest.setConditions(map);
        User user;
        try {

            System.out.println("登陆时传来的加密后的密码："+loginBody.getPassword());
            System.out.println("正确的密码加密之后："+AESUtils.encrypt("12"));
            user = getUserByUsername(pageRequest);
            if (user!=null) {
                String userIsUpdatePwd = userMapper.checkUserIsUpdatePwd(user.getId());
                //System.out.println("是否需要修改密码：" + userIsUpdatePwd);
                user.setIsUpdatePwd(userIsUpdatePwd);
                Date userLockAt = user.getLockAt();
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.MINUTE, -LOCK_MINUTES);
                if(userLockAt==null||(userLockAt!=null&&userLockAt.before(calendar.getTime()))){
                    //解密密码，在前端加密后启用
                    loginBody.setPassword(AESUtils.decrypt(loginBody.getPassword()));
                    if(SecurityUtils.matchesPassword(loginBody.getPassword(), user.getPassword())) {
                        if(user.getStatus().equals("2")){
                            return CommonResult.failed("该账号已失效");
                        }

                        String deptName = "";
                        if(!BlankUtils.isBlank(user.getDeptId())){
                            Department department = departmentMapper.selectByPrimaryKey(user.getDeptId());
                            deptName = department.getDeptName();
                        }
                        UserBean userBean = new UserBean(user, deptName);
                        CommonResult companyDic = getCompanyList();
                        List<Company> companyList = (List<Company>)companyDic.getData();
                        for(Company company :companyList){
                            if(company.getId().equals(user.getCoId())){
                                userBean.setCoName(company.getName());
                                break;
                            }
                        }
                        user.setPwdErrTimes((short)0);
//                        user.setLastLoginIp(getIpAddress());
                        user.setLastLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
                        Date date = new Date();
                        user.setLastLoginTime(date);
                        user.setLockAt(null);
                        editUserBasic(user);

                        return CommonResult.success(userBean, "登陆成功");
                    } else {
                        if(user.getPwdErrTimes()+1 < ALLOWED_ERROR_TIME){
                            user.setPwdErrTimes((short)(user.getPwdErrTimes()+1));
                            editUserBasic(user);
                        } else {
                            user.setPwdErrTimes((short)0);
                            Date date = new Date();
                            user.setLockAt(date);
                            editUserBasic(user);
                            return CommonResult.failed("登陆失败，密码错误达到"+ALLOWED_ERROR_TIME+"次，账号将被禁用"+LOCK_MINUTES+"分钟");
                        }
                        //return CommonResult.failed("登陆失败，密码错误");
                        return CommonResult.failed("用户名或密码错误");
                    }
                } else {
                    return CommonResult.failed("该账号因错误次数过多而上锁");
                }
            } else {
                //return CommonResult.failed("登陆失败，没有此用户");
                return CommonResult.failed("用户名或密码错误");
            }
        } catch (Exception e){
            return CommonResult.failed(e.getMessage());
        }
    }

    @Override
    public CommonResult<UserBean> loginByOpenId(LoginByOpenIdBody loginByOpenIdBody){
        //以后这里的参数要从系统表中获取。
        final Integer ALLOWED_ERROR_TIME = 3;
        final Integer LOCK_MINUTES = 3;

        System.out.println("loginByPassword");
        if(loginByOpenIdBody.getOpenId()==null){
            return CommonResult.failed("openId为空");
        }

        try {
            UserExample userExample = new UserExample();
            UserExample.Criteria criteria = userExample.createCriteria();
            criteria.andOpenIdEqualTo(loginByOpenIdBody.getOpenId());
            List<User> userList = userMapper.selectByExample(userExample);
            if (userList.size() == 0) {
                return CommonResult.failed("没有和本OpenId绑定的用户信息");
            }
            User user = userList.get(0);

            String deptName = "";
            if(!BlankUtils.isBlank(user.getDeptId())){
                Department department = departmentMapper.selectByPrimaryKey(user.getDeptId());
                deptName = department.getDeptName();
            }
            UserBean userBean = new UserBean(user, deptName);

            CommonResult companyDic = getCompanyList();
            List<Company> companyList = (List<Company>)companyDic.getData();
            for(Company company :companyList){
                if(company.getId().equals(user.getCoId())){
                    userBean.setCoName(company.getName());
                    break;
                }
            }

//                        user.setLastLoginIp(getIpAddress());
            user.setLastLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
            Date date = new Date();
            user.setLastLoginTime(date);
            user.setLockAt(null);
            editUserBasic(user);
            return CommonResult.success(userBean, "登陆成功");

        } catch (Exception e){
            return CommonResult.failed(e.getMessage());
        }
    }

    //修改用户的除密码、角色外的基本信息，防止触发复杂的操作。
    //如果有修改密码或是角色的可能，请用editUser接口。
    public CommonResult editUserBasic(User user){
        try {
            User targetUser = userMapper.selectByPrimaryKey(user.getId());
            if (targetUser==null){
                return CommonResult.failed("无法找到此用户");
            } else {
                //将密码、角色置空（从而更新时不改变已有的），并且删除无关的业务逻辑
                user.setPassword(null);
                user.setRoleStr(null);
                if (userMapper.updateByPrimaryKeySelective(user) != 1) {
                    return CommonResult.failed("更新用户失败");
                } else {
                    return CommonResult.success(null, "更新用户成功");
                }
            }
        } catch (Exception e){
            return CommonResult.failed("连接错误或无法找到此用户");
        }
    }

    public User getUserByUsername(PageRequest pageRequest) throws Exception{
        try{
            return userMapper.getUserByUsername(pageRequest);
        } catch (Exception e) {
            throw e;
        }
    }

    public CommonResult getCompanyList(){
        try {
            CompanyExample companyExample = new CompanyExample();
            CompanyExample.Criteria criteria = companyExample.createCriteria();
            List<Company> companyList = companyMapper.selectByExample(companyExample);
            return CommonResult.success(companyList, "单位字典表获取成功");
        } catch (Exception e){
            return CommonResult.failed(e.getMessage());
        }
    }

    public CommonResult registerTest(String username, String password){
        User user = new User();
        user.setCoId((short)2);
        user.setLoginName(username);
        user.setUserName("测试用账号"+ (int)(Math.random()*1000));
        user.setPassword(password);
        user.setPwdSalt(password);
        user.setPwdAlg(password);
        user.setStatus("1");
        user.setIsDeleted("0");
        if(userMapper.insert(user)==1){
            return CommonResult.success(null, "账号添加成功");
        } else {
            return CommonResult.failed("账号添加失败");
        }
    }

    // 方法1
    private String getNowIP1() throws IOException {
        String ip = null;
        String chinaz = "http://ip.chinaz.com";
        StringBuilder inputLine = new StringBuilder();
        String read = "";
        URL url = null;
        HttpURLConnection urlConnection = null;
        BufferedReader in = null;
        try {
            url = new URL(chinaz);
            urlConnection = (HttpURLConnection) url.openConnection();
            in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
            while ((read = in.readLine()) != null) {
                inputLine.append(read + "\r\n");
            }
            Pattern p = Pattern.compile("\\<dd class\\=\"fz24\">(.*?)\\<\\/dd>");
            Matcher m = p.matcher(inputLine.toString());
            if (m.find()) {
                String ipstr = m.group(1);
                ip = ipstr;
            }
        } finally {
            if (in != null) {
                in.close();
            }
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }
    // 方法2
    private String getNowIP2() throws IOException {
        String ip = null;
        BufferedReader br = null;
        try {
            URL url = new URL("https://v6r.ipip.net/?format=callback");
            br = new BufferedReader(new InputStreamReader(url.openStream()));
            String s = "";
            StringBuffer sb = new StringBuffer("");
            String webContent = "";
            while ((s = br.readLine()) != null) {
                sb.append(s + "\r\n");
            }
            webContent = sb.toString();
            int start = webContent.indexOf("(") + 2;
            int end = webContent.indexOf(")") - 1;
            webContent = webContent.substring(start, end);
            ip = webContent;
        } finally {
            if (br != null)
                br.close();
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }
    // 方法3
    private String getNowIP3() throws IOException {
        String ip = null;
        String objWebURL = "https://ip.900cha.com/";
        BufferedReader br = null;
        try {
            URL url = new URL(objWebURL);
            br = new BufferedReader(new InputStreamReader(url.openStream()));
            String s = "";
            String webContent = "";
            while ((s = br.readLine()) != null) {
                if (s.indexOf("我的IP:") != -1) {
                    ip = s.substring(s.indexOf(":") + 1);
                    break;
                }
            }
        } finally {
            if (br != null)
                br.close();
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }
    // 方法4-可行
    private String getNowIP4() throws IOException {
        String ip = null;
        String objWebURL = "https://bajiu.cn/ip/";
        BufferedReader br = null;
        try {
            URL url = new URL(objWebURL);
            br = new BufferedReader(new InputStreamReader(url.openStream()));
            String s = "";
            String webContent = "";
            while ((s = br.readLine()) != null) {
                if (s.indexOf("互联网IP") != -1) {
                    ip = s.substring(s.indexOf("'") + 1, s.lastIndexOf("'"));
                    break;
                }
            }
        } finally {
            if (br != null)
                br.close();
        }
        if (StringUtils.isEmpty(ip)) {
            throw new RuntimeException();
        }
        return ip;
    }

    // 获取用户的公网IP地址。摘自https://www.jianshu.com/p/d985711629da
    //现在已经不用了
    public String getIpAddress() {
        String ip = null;
        // 第一种方式
        try {
            ip = this.getNowIP1();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP1 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        // 第二种方式
//        try {
//            ip = this.getNowIP2();
//            ip.trim();
//        } catch (Exception e) {
//            System.out.println("getPublicIP - getNowIP2 failed ~ ");
//        }
//        if (!StringUtils.isEmpty(ip))
//            return ip;
        // 第三种方式
        try {
            ip = this.getNowIP3();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP3 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        // 第四种方式
        try {
            ip = this.getNowIP4();
            ip.trim();
        } catch (Exception e) {
            System.out.println("getPublicIP - getNowIP4 failed ~ ");
        }
        if (!StringUtils.isEmpty(ip))
            return ip;
        return ip;
    }
}
